package lib.self.util.autoFit;

import android.content.Context;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewGroup.MarginLayoutParams;
import android.view.ViewTreeObserver.OnPreDrawListener;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import androidx.constraintlayout.widget.ConstraintLayout;

import java.util.HashSet;
import java.util.Set;

/**
 * description: 自动获取view的xml的参数(dp)，根据分辨率的scale重新设置大小(px)
 * author: Steven Xiao
 * date: 2017/4/24
 */
public class FitViewParamsUtil {
    public static final int MATCH_PARENT = LayoutParams.MATCH_PARENT;
    public static final int WRAP_CONTENT = LayoutParams.WRAP_CONTENT;

    public static Set<View> mSetFit = new HashSet<>();

    /**
     * 处理宽高专用
     */
    private static int getTransformPxWH(int value, Context context) {
        if (value == 0 || value == MATCH_PARENT || value == WRAP_CONTENT || value == 1) {
            return value;
        }
        int ret = (int) FitDpUtil.densityPxToScalePx(value, context);
        return ret;
    }

    /**
     * 处理其他值
     *
     * @param value
     * @param context
     * @return
     */
    private static int getTransformPx(int value, Context context) {
        if (value == 0 || value == 1 || value == -1) {
            return value;
        }
        int ret = (int) FitDpUtil.densityPxToScalePx(value, context);
        return ret;
    }

    private static int getTransformPx(float value, Context context) {
        return getTransformPx((int) value, context);
    }

    /**
     * 获取TextView的行距
     *
     * @param textView
     * @return
     */
    private static float getTvLineSpacingExtra(TextView textView) {
        return textView.getLineSpacingExtra();
    }

    /**
     * 设置TextView行距
     *
     * @param textView
     */
    private static void setTvLineSpacingExtra(TextView textView) {
        textView.setLineSpacing(getTransformPx(getTvLineSpacingExtra(textView), textView.getContext()), 1);
    }

    private static void fitTvParams(TextView textView) {
        Context context = textView.getContext();
        setTvLineSpacingExtra(textView);
        textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, getTransformPx(textView.getTextSize(), context));

        //TextView   drawableLeft DrawableTop DrawableRight DrawableBottom  0左 1顶 2右 3下
        Drawable[] compoundDrawables = textView.getCompoundDrawables();
        textView.setCompoundDrawablePadding(getTransformPx(textView.getCompoundDrawablePadding(), context));
        for (int i = 0; i < compoundDrawables.length; i++) {
            Drawable drawable = compoundDrawables[i];
            if (drawable != null) {
                Rect rect = new Rect(0, 0, getTransformPx(drawable.getIntrinsicWidth(), context), getTransformPx(drawable.getIntrinsicHeight(), context));
                drawable.setBounds(rect);
            }
        }
    }

    /**
     * 改变控件的数值
     *
     * @param view
     * @param params
     */
    private static void setMarginParams(View view, MarginLayoutParams params) {
        Context context = view.getContext();

        //修改宽高
        params.width = getTransformPxWH(params.width, context);
        params.height = getTransformPxWH(params.height, context);

        //修改margin值
        params.leftMargin = getTransformPx(params.leftMargin, context);
        params.rightMargin = getTransformPx(params.rightMargin, context);
        params.topMargin = getTransformPx(params.topMargin, context);
        params.bottomMargin = getTransformPx(params.bottomMargin, context);

        //修改padding值
        int paddingLeft = getTransformPx(view.getPaddingLeft(), context);
        int paddingTop = getTransformPx(view.getPaddingTop(), context);
        int paddingRight = getTransformPx(view.getPaddingRight(), context);
        int paddingBottom = getTransformPx(view.getPaddingBottom(), context);
        view.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);
    }

    /**
     * 适配父布局为ViewGroup的view
     *
     * @param view
     */
    public static void fitParams(View view) {
        if (view.getParent() instanceof RelativeLayout || view.getParent() instanceof LinearLayout
                || view.getParent() instanceof FrameLayout || view.getParent() instanceof ConstraintLayout) {
            MarginLayoutParams params = (MarginLayoutParams) view.getLayoutParams();
            setMarginParams(view, params);
            view.setLayoutParams(params);
        }
    }

    public static void autoFitAll(View view) {
        if (view instanceof ViewGroup) {
            autoFitAll((ViewGroup) view, false);
        } else if (view instanceof TextView) {
            fitTvParams((TextView) view);
            fitParams(view);
        }
    }

    private static void autoFitAll(final ViewGroup viewGroup, boolean addListener) {
        if (addListener) {
            if (viewGroup.getViewTreeObserver().isAlive()) {
                viewGroup.getViewTreeObserver().addOnPreDrawListener(new OnPreDrawListener() {
                    @Override
                    public boolean onPreDraw() {
                        processChildren(viewGroup);
                        viewGroup.getViewTreeObserver().removeOnPreDrawListener(this);
                        return false;
                    }
                });
            }
        } else {
            processChildren(viewGroup);
        }
    }

    private static void processChildren(ViewGroup viewGroup) {
        for (int i = 0; i < viewGroup.getChildCount(); i++) {
            View view = viewGroup.getChildAt(i);
            if (mSetFit.contains(view)) {
                continue;
            } else {
                mSetFit.add(view);
            }

            if (view instanceof ViewGroup) {
                autoFitAll(view);
            }

            if (view instanceof TextView) {
                fitTvParams((TextView) view);
            }

            fitParams(view);
        }
    }

    public static void removeFromFitSet(View view) {
        mSetFit.remove(view);
    }

    public static void clearFitSet() {
        mSetFit.clear();
    }
}
